package com.leantech.android.browser.ui.browser.viewmodel

import android.graphics.Bitmap
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.cscj.android.repository.datastore.AppDataStore
import com.cscj.android.repository.db.entity.HotSearchEntity
import com.cscj.android.repository.db.entity.SearchEngineEntity
import com.cscj.android.repository.db.entity.UserAgentEntity
import com.cscj.android.repository.repo.config.WebConfigRepository
import com.cscj.android.repository.repo.config.WebViewConfig
import com.cscj.android.repository.repo.favorites.FavoritesRepository
import com.cscj.android.repository.repo.history.BrowserHistoryRepository
import com.cscj.android.repository.repo.search.SearchRepository
import com.cscj.android.repository.settings.Settings
import com.cscj.android.repository.settings.model.SettingConstants
import com.cscj.android.utils.formatHumanReadableDay
import com.leantech.android.browser.ui.favorites.vm.BrowserHistoryViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class BrowserViewModel : ViewModel(), KoinComponent {

    private val uaSettings: Settings.UserAgentSetting by inject()

    private val browserSetting by inject<Settings.BrowserSetting>()

    private val appDataStore by inject<AppDataStore>()

    private val searchRepository by inject<SearchRepository>()

    private val browserHistoryRepository by inject<BrowserHistoryRepository>()

    private val favoritesRepository by inject<FavoritesRepository>()

    private val webConfigRepository by inject<WebConfigRepository>()


    private val policyUrl = getKoin().getProperty("policyUrl", "")
    private val serviceUrl = getKoin().getProperty("serviceUrl", "")

    init {
        viewModelScope.launch {
            searchRepository.loadHotSearch()
        }
    }

    var menuPageIndex = 0


    val imageModeFlow = browserSetting.imageModeFlow().stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = SettingConstants.DefaultImageMode
    )

    fun getCurrentImageMode(): Int {
        return runBlocking {
            browserSetting.imageModeFlow().firstOrNull() ?: SettingConstants.DefaultImageMode
        }
    }

    fun updateImageMode(imageMode: Int) {
        viewModelScope.launch {
            browserSetting.updateImageMode(imageMode)
        }
    }


    val darkModeFlow = browserSetting.darkModeFlow().stateIn(
        scope = viewModelScope,
        started = SharingStarted.WhileSubscribed(5000),
        initialValue = SettingConstants.DefaultDarkMode
    )

    fun getCurrentDarkMode(): Int {
        return runBlocking {
            browserSetting.darkModeFlow().firstOrNull() ?: SettingConstants.DefaultImageMode
        }
    }

    fun updateDarkMode(darkMode: Int) {
        viewModelScope.launch {
            browserSetting.updateDarkMode(darkMode)
        }
    }


    val currentUaFlow = uaSettings.currentUserAgent().stateIn(
        scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = null
    )

    fun userAgentList(): List<UserAgentEntity> {
        return runBlocking {
            uaSettings.userAgentList().first()
        }
    }

    fun switchUserAgent(id: Int) {
        viewModelScope.launch {
            uaSettings.switchUserAgent(id)
        }
    }

    val fontSizeFlow = browserSetting.fontSizeFlow().stateIn(
        scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = 100
    )

    fun getCurrentFontSize(): Int {
        return runBlocking {
            browserSetting.fontSizeFlow().firstOrNull() ?: 100
        }
    }

    fun updateFontSize(fontSize: Int) {
        viewModelScope.launch {
            browserSetting.updateFontSize(fontSize)
        }
    }

    val readerModeFlow = browserSetting.readerModeFlow().stateIn(
        scope = viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = false
    )

    fun currentReaderMode(): Boolean {
        return runBlocking {
            readerModeFlow.firstOrNull() ?: false
        }
    }

    fun updateReaderMode(on: Boolean) {
        viewModelScope.launch {
            browserSetting.updateReaderMode(on)
        }
    }


    val privacyModeFlow = browserSetting.privacyModeFlow().stateIn(
        viewModelScope, SharingStarted.WhileSubscribed(5000), false
    )

    fun currentPrivacyMode() = privacyModeFlow.value

    fun switchPrivacyMode(enable: Boolean) {
        viewModelScope.launch {
            browserSetting.updatePrivacyMode(enable)
        }
    }

    val lockPortraitFlow = browserSetting.lockPortraitFlow().stateIn(
        viewModelScope, SharingStarted.WhileSubscribed(5000), false
    )

    fun currentLockPortrait() = lockPortraitFlow.value

    fun switchLockPortrait(lock: Boolean) {
        viewModelScope.launch {
            browserSetting.updateLockScreen(lock)
        }
    }

    fun getCurrentSearchEngine(): SearchEngineEntity? {
        return runBlocking {
            searchRepository.currentSearchEngine().firstOrNull()
        }
    }

    fun addToHistory(title: String, url: String, favicon: Bitmap?) {
        if (!currentPrivacyMode() && !url.startsWith(policyUrl) && !url.startsWith(
                serviceUrl
            )
        ) {
            viewModelScope.launch {
                browserHistoryRepository.addBrowserHistory(title, url, favicon)
            }
        }
    }

    fun clearHistory() {
        viewModelScope.launch {
            browserHistoryRepository.clearAllHistory()
        }
    }

    fun clearSearchHistory() {
        viewModelScope.launch {
            searchRepository.deleteAllSearchHistory()
        }
    }


    //hot search
    val baiduHotSearchFlow =
        searchRepository.hotSearchList(HotSearchEntity.SourceTypeBaidu).stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )

    val toutiaoHotSearchFlow =
        searchRepository.hotSearchList(HotSearchEntity.SourceTypeTouTiao).stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )

    val zhihuHotSearchFlow =
        searchRepository.hotSearchList(HotSearchEntity.SourceTypeZhihu).stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )

    val zongyiHotSearchFlow =
        searchRepository.hotSearchList(HotSearchEntity.SourceTypeZongYi).stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )

    val weiboHotSearchFlow =
        searchRepository.hotSearchList(HotSearchEntity.SourceTypeWeibo).stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = emptyList()
        )

    fun updateFavicon(url: String, favicon: Bitmap?) {
        viewModelScope.launch {
            browserHistoryRepository.updateFavicon(url, favicon)
            favoritesRepository.updateFavicon(url, favicon)
        }
    }

    val webConfigFlow = webConfigRepository.getWebViewConfigFlow()
        .stateIn(
            scope = viewModelScope,
            started = SharingStarted.WhileSubscribed(5000),
            initialValue = WebViewConfig()
        )

    fun updateBlockIntent(block: Boolean) {
        viewModelScope.launch {
            browserSetting.updateBlockIntent(block)
        }
    }

    fun getWebConfig(): WebViewConfig {
        return webConfigFlow.value
    }

    //历史记录
    private val _historySearchKeywordFlow = MutableStateFlow<String?>(null)

    private val _historyFlow = _historySearchKeywordFlow.flatMapLatest { keyword ->
        browserHistoryRepository.browserHistoryList(keyword)
    }

    val historyFlow = _historyFlow.map { list ->
        val result = mutableListOf<BrowserHistoryViewModel.HistoryItem>()
        list.forEach { browseHistoryEntity ->
            val titleText = formatHumanReadableDay(browseHistoryEntity.visitTime.time)
            val hasTitle = result.find { item ->
                item is BrowserHistoryViewModel.HistoryItem.Title && item.title == titleText
            } != null

            if (!hasTitle) {
                result.add(BrowserHistoryViewModel.HistoryItem.Title(titleText))
            }
            result.add(BrowserHistoryViewModel.HistoryItem.Item(browseHistoryEntity))
        }
        result
    }

    val showAdBlockEntryFlow = appDataStore.showAdBlockEntry()

    fun updateAdBlockTime() {
        viewModelScope.launch {
            appDataStore.updateBlockAdTime()
        }
    }

}